#pragma once
#include "noncopyable.h"
#include "EventLoop.h"
#include "Acceptor.h"
#include "InetAddress.h"
#include <functional>
#include <string>
#include <memory>
#include "EventLoopThreadPoll.h"
#include "Callbacks.h"
#include <atomic>
#include <unordered_map>

/**
 * @brief 用户使用muduo编写服务器程序
 * 
 */
//对外的服务器编程使用的类
class TcpServer : noncopyable {
    public:
        using ThreadInitCallback = std::function<void(EventLoop *)>;
        enum Option {
            kNoReusePort,
            kReusePort,
        };
        TcpServer(EventLoop *loop, //传给tcpserver的是用户创建的mainloop
                const InetAddress& listenAddr,
                const std::string& nameArg,
                Option option = kNoReusePort);
        ~TcpServer();

        // 设置subloop个数
        void setThreadNum(int numThreads);

        void setThreadInitCallback(const ThreadInitCallback& cb) { threadInitCallback_ = cb; }
        void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; }
        void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; }
        void setWriteCompleteCallback(const WriteCompleteCallback& cb) { writeCompleteCallback_ = cb; }

        void start();//开启服务器


    private:
        void newConnection(int sockfd, const InetAddress& peerAddr);
        void removeConnection(const TcpConnection &conn);
        void removeConnectionInLoop(const TcpConnection& conn);

        using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>;

        EventLoop *loop_; // the acceptor loop
        const std::string ipPort_;
        const std::string name_; // 服务器名字


        std::unique_ptr<Acceptor> acceptor_; // 运行在mainloop，监听来连接事件
        std::shared_ptr<EventLoopThreadPool> threadPool_;

        ConnectionCallback connectionCallback_; // 有新连接时的回调
        MessageCallback messageCallback_; // 都读写消息的回调
        WriteCompleteCallback writeCompleteCallback_; //消息发送完成以后的回调
        ThreadInitCallback threadInitCallback_; // loop线程初始化的回调
        std::atomic_int started_;

        int nextConnId_;
        ConnectionMap connections_; //保存所有连接

};